﻿using AutoMapper;
using ManagementApi.Authorizers;
using ManagementApi.Models;
using ManagementApi.Models.Notify;
using ManagementApi.Models.Person;
using ManagementApi.Mvc;
using ManagementApi.Mvc.ApplicationContexts;
using ManagementApi.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Modules.Entitys;
using Modules.Notify;
using Modules.Project;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using PmSoft.Exceptions;

namespace ManagementApi.Controllers.ManagerPannel
{
    /// <summary>
    /// 工人通知相关业务接口
    /// </summary>
    [Route("/api/v1/manager/workernotify")]
    [ApiController]
    [Authorize(Roles = "Manager")]
    public class WorkerNotifyController : ControllerBase
    {
        private readonly IMapper mapper;
        private readonly WorkerNotifyService workerNotifyService;
        private readonly ProjectManagerApplicationContext applicationContext;
        private readonly ExportService exportService;
        private readonly ProjectService projectService;
        private readonly ProjectOwnAuthorizer ownAuthorizer;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="workerNotifyService"></param>
        /// <param name="mapper"></param>
        public WorkerNotifyController(
             IMapper mapper,
             WorkerNotifyService workerNotifyService,
             ProjectManagerApplicationContext applicationContext,
              ExportService exportService,
              ProjectService projectService,
              ProjectOwnAuthorizer ownAuthorizer
            )
        {
            this.mapper = mapper;
            this.workerNotifyService = workerNotifyService;
            this.applicationContext = applicationContext;
            this.exportService = exportService;
            this.projectService = projectService;
            this.ownAuthorizer = ownAuthorizer;
        }

        /// <summary>
        /// 获取工人通知列表
        /// </summary>
        /// <param name="query">查询条件</param>
        /// <param name="pageNum">页码</param>
        /// <param name="pageSize">每页数量</param>
        /// <returns></returns>
        [HttpGet("page")]
        public ApiResult<PageDto<WorkerNotifyDto>> GetWorkerNotifysByPage([FromQuery] NotifyQuery query, int pageNum = 1, int pageSize = 20)
        {
            query.ProjectId = applicationContext.CurrentProjectInfo.ProjectId;
            var sysNotifies = workerNotifyService.GetWorkerNotifysByPage(query, pageNum, pageSize);
            var dtos = sysNotifies.AsPageDto(source => { return source.AsWorkerNotifyDto(); });
            return ApiResult<PageDto<WorkerNotifyDto>>.Success(dtos);
        }

        /// <summary>
        /// 创建工人通知
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        [HttpPost("add")]
        public ApiResult AddWorkerNotify(WorkerNotifyEditForm form)
        {
            WorkerNotify notify = new WorkerNotify();
            mapper.Map(form, notify);
            notify.ProjectId = applicationContext.CurrentProjectInfo.ProjectId;
            workerNotifyService.CreateWorkerNotify(notify, form.AttachmentIds ?? new List<string>());
            return ApiResult.Success("添加成功");
        }

        /// <summary>
        /// 修改工人通知
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        [HttpPut("update")]
        public ApiResult EditWorkerNotify(WorkerNotifyEditForm form)
        {
            if (string.IsNullOrEmpty(form.Id))
            {
                return ApiResult.Failure("修改失败,未传Id");
            }
            WorkerNotify notify = workerNotifyService.GetWorkerNotify(form.Id) ?? new WorkerNotify();

            #region 验证数据权限

            ownAuthorizer.CheckAndThrowIfOwnAuthenticationFailed(notify.ProjectId);

            #endregion 验证数据权限

            mapper.Map(form, notify);
            notify.CreateTime = DateTime.Now;
            notify.ReadedNum = 0;
            workerNotifyService.UpdateWorkerNotify(notify, form.AttachmentIds ?? new List<string>());
            return ApiResult.Success("修改成功");
        }

        /// <summary>
        /// 获取工人通知详情
        /// </summary>
        /// <param name="id">查询条件</param>
        /// <returns></returns>
        [HttpGet("form/{id}")]
        public ApiResult<WorkerNotifyDto> GetWorkerNotifyById(string id)
        {
            if (string.IsNullOrEmpty(id) || id == "0")
            {
                return ApiResult<WorkerNotifyDto>.Success(new WorkerNotifyDto()
                {
                    Id = Guid.NewGuid().ToString().Replace("-", ""),
                });
            }
            var workerNotify = workerNotifyService.GetWorkerNotify(id);
            if (workerNotify == null)
            {
                return ApiResult<WorkerNotifyDto>.Failure("查询失败，通知不存在");
            }
            return ApiResult<WorkerNotifyDto>.Success(workerNotify.AsWorkerNotifyDto());
        }

        /// <summary>
        /// 删除工人通知
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpDelete("del/{id}")]
        public ApiResult Delete(string id)
        {
            WorkerNotify notify = workerNotifyService.GetWorkerNotify(id) ?? throw new BusinessException("数据不存在");

            #region 验证数据权限

            ownAuthorizer.CheckAndThrowIfOwnAuthenticationFailed(notify.ProjectId);

            #endregion 验证数据权限

            workerNotifyService.DeleteWorkerNotify(id);
            return ApiResult.Success("删除成功");
        }

        /// <summary>
        /// 导出工人通知
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        [HttpGet("export")]
        public IActionResult ExportDetail([FromQuery] NotifyQuery query)
        {
            List<WorkerNotify> workers = workerNotifyService.GetAllWorkerNotifysByQuery(query).ToList();
            ProjectInfo? projectInfo = projectService.GetProjectInfo(applicationContext.CurrentProjectInfo.ProjectId);
            if (projectInfo == null)
                throw new BusinessException($"项目信息不存在");
            if (workers.Count() == 0)
            {
                throw new BusinessException($"通知信息不存在");
            }

            #region 生成Excel部分

            // 创建一个新的Excel工作簿
            IWorkbook workbook = new XSSFWorkbook();

            // 创建一个新的工作表
            ISheet sheet = workbook.CreateSheet("Sheet1");
            // 创建列并设置最小宽度
            int columnWidth = 20;
            int columnIndex = 0;
            sheet.SetColumnWidth(columnIndex, columnWidth * 256); // 设定列宽度，参数为1/256个字符宽度

            // 自动调整列宽
            for (int i = 0; i < 8; i++)
            {
                // 自动调整列宽
                //sheet.AutoSizeColumn(i);
                sheet.SetColumnWidth(i, Math.Max(columnWidth * 256, sheet.GetColumnWidth(i)));
            }
            int index = 4;

            #region 表头

            // 合并行和列的方式设置单元格的边界
            CellRangeAddress region = new CellRangeAddress(0, 1, 0, 7);
            sheet.AddMergedRegion(region);
            // 创建一个新的行
            IRow row = sheet.CreateRow(0);
            ICell cell = row.CreateCell(0);
            // 创建字体对象
            IFont font = workbook.CreateFont();
            font.FontHeightInPoints = 20; // 设置字体大小为 12

            // 设置单元格样式
            ICellStyle cellStyle = workbook.CreateCellStyle();
            cellStyle.Alignment = HorizontalAlignment.Center;//居中
            cellStyle.SetFont(font);
            cell.CellStyle = cellStyle;
            // 设置单元格的值
            if (query.Month.HasValue)
            {
                cell.SetCellValue($"{projectInfo.Name}{string.Format("{0:yyyy-MM}", query.Month)}工人通知");
            }
            else
            {
                cell.SetCellValue($"{projectInfo.Name}工人通知");
            }

            #endregion 表头

            #region 中间部分

            exportService.CellRange(sheet, workbook, index, 0, "序号", "通知标题", "通知内容", "发布人", "发布日期", "查看次数");

            #region 数据部分

            int rows = 1;
            for (int i = 0; i < workers.Count(); i++)
            {
                var title = workers[i].Title;
                var content = workers[i].Content;
                var creator = workers[i].Creator;
                var createTime = workers[i].CreateTime.ToString("yyyy-MM-dd");
                var readedNum = workers[i].ReadedNum;
                exportService.CellRange(sheet, workbook, index, 0, rows.ToString(), title, content, creator, createTime, readedNum.ToString());
                index++;
                rows++;
            }

            #endregion 数据部分

            #endregion 中间部分

            // 将工作簿保存到内存流中
            using (MemoryStream memoryStream = new MemoryStream())
            {
                workbook.Write(memoryStream);
                // 设置要下载的文件名
                string fileName = $"{projectInfo.Name}工人通知.xlsx";

                if (query.Month.HasValue)
                {
                    fileName = $"{projectInfo.Name}{string.Format("{0:yyyy-MM}", query.Month)}工人通知.xlsx";
                }

                // 返回文件内容结果
                return File(memoryStream.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName);
            }

            #endregion 生成Excel部分
        }
    }
}